package genedit.gui.propertyDialogs;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import genedit.gui.GMainFrame;
import genedit.gui.exceptions.ElementNePostoji;
import genedit.gui.exceptions.ElementPostoji;
import genedit.model.graph.ConnectionPoint;
import genedit.model.graph.GraphElement;
import genedit.model.graph.Link;
import genedit.model.graph.Property;
import genedit.model.graph.classModel.ClassModel;
import genedit.model.graph.classModel.GAttribute;
import genedit.model.graph.classModel.GAttribute.VisibilityType;
import genedit.model.graph.classModel.GAttributes;
import genedit.model.graph.classModel.GMethod;
import genedit.model.graph.classModel.GMethods;
import genedit.model.graph.classModel.GParameter;
import genedit.model.graph.classModel.GeneralizationLink;
import genedit.model.graph.classModel.ITableModel;
import genedit.model.graph.classModel.InterfaceModel;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;

import com.sun.corba.se.impl.orbutil.graph.Graph;





@SuppressWarnings("serial")
public class ClassModelDialog extends AbstractDialog{

	protected JTable tableAttributes;
	protected String[] tableColumnsAttributes;
	protected JTable tableMethods;
	protected String[] tableColumnsMethods;
	protected DialogTableModel tableModelAttributes;
	protected DialogTableModel tableModelMethods;
	protected JCheckBox chbAbstract;
	protected JCheckBox chbStatic;
	protected JCheckBox chbFinal;
	protected JLabel lblAbstract;
	protected JLabel lblStatic;
	protected JLabel lblFinal;
	protected ClassModel modelEl; 
	
	public ClassModelDialog(JFrame parent, GraphElement element) {
		super(parent);
		this.element = element;
		setTitle(element.getName());
		
		tableColumnsAttributes = new String[6];
		tableColumnsAttributes[0] = GMainFrame.getInstance().getResourceBundle().getString("lblVisibility");
		tableColumnsAttributes[1] = GMainFrame.getInstance().getResourceBundle().getString("lblType");
		tableColumnsAttributes[2] = GMainFrame.getInstance().getResourceBundle().getString("lblName");
		tableColumnsAttributes[3] = GMainFrame.getInstance().getResourceBundle().getString("lblPredef");
		tableColumnsAttributes[4] = "Get";
		tableColumnsAttributes[5] = "Set";
	
		for (Property p : ((ClassModel)element).getProperties()) {
			if(p.getKey().equals("attributes"))
			tableModelAttributes = new DialogTableModel(tableColumnsAttributes, (GAttributes)p.getValue());
		}
		
		tableColumnsMethods = new String[4];
		tableColumnsMethods[0] = GMainFrame.getInstance().getResourceBundle().getString("lblVisibility");
		tableColumnsMethods[1] = GMainFrame.getInstance().getResourceBundle().getString("lblRetType");
		tableColumnsMethods[2] = GMainFrame.getInstance().getResourceBundle().getString("lblName");
		tableColumnsMethods[3] = GMainFrame.getInstance().getResourceBundle().getString("lblParameter");
	
		for (Property p : ((ClassModel)element).getProperties()) {
			if(p.getKey().equals("methods"))
				tableModelMethods = new DialogTableModel(tableColumnsMethods, (GMethods)p.getValue());
		}
		
		
		initGUI();
		
		Dimension lblDimension = new Dimension(50,20);
		lblAbstract = new JLabel("Abstract");
		lblAbstract.setPreferredSize(lblDimension);
		chbAbstract = new JCheckBox();
		chbAbstract.setSelected(((ClassModel)element).isAbstractEl());
		panClassAttributes.add(lblAbstract);
		panClassAttributes.add(chbAbstract);
		
		//Dimension lblDimension = new Dimension(50,20);
		lblStatic = new JLabel("Static");
		lblStatic.setPreferredSize(lblDimension);
		chbStatic = new JCheckBox();
		chbStatic.setSelected(((ClassModel)element).isStaticEl());
		panClassAttributes.add(lblStatic);
		panClassAttributes.add(chbStatic);
		
		//Dimension lblDimension = new Dimension(50,20);
		lblFinal = new JLabel("Final");
		lblFinal.setPreferredSize(lblDimension);
		chbFinal = new JCheckBox();
		chbFinal.setSelected(((ClassModel)element).isFinaltEl());
		panClassAttributes.add(lblFinal);
		panClassAttributes.add(chbFinal);
		
		JPanel panTableAttributes = new JPanel(new BorderLayout());
		panTableAttributes.setBackground(Color.WHITE);
		tableAttributes = new JTable(tableModelAttributes);
		tableAttributes.setAutoCreateRowSorter(true);
		tableAttributes.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		tableAttributes.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		
		panTableAttributes.add(new JScrollPane(tableAttributes), BorderLayout.CENTER);
		
		
		JPanel panTableMethods = new JPanel(new BorderLayout());
		panTableMethods.setBackground(Color.WHITE);
		tableMethods = new JTable(tableModelMethods);
		tableMethods.setAutoCreateRowSorter(true);
		tableMethods.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		tableMethods.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		
		panTableMethods.add(new JScrollPane(tableMethods), BorderLayout.CENTER);
		
		JPanel panSouth = new JPanel();
		panSouth.setLayout(new BoxLayout(panSouth, BoxLayout.PAGE_AXIS));
		 modelEl = (ClassModel)this.element;
		 btnOkDialog = new JButton(GMainFrame.getInstance().getResourceBundle().getString("btnOk"));
		 btnOkDialog.addActionListener(new ActionListener() {
			 
			 private void goDepth(GraphElement model) {
				 		performPropagation(model);
						ArrayList<GraphElement> row = new ArrayList<GraphElement>();
						 for(ConnectionPoint cp : model.getConnectionPoints()){
								for(Link link : cp.getEnding())
									if(link instanceof GeneralizationLink)
									row.add(link.getStart().getParent());
						 }
						 if(row.size()!=0)
							 for(GraphElement element : row)
								 goDepth(element);
						 else return;
			 }
			 
			 private void performPropagation(GraphElement model) {
				 for(ConnectionPoint cp : model.getConnectionPoints()){
						for(Link link : cp.getEnding()){
							if(link instanceof GeneralizationLink) {
								for (Property p : model.getProperties()) {
									if(p.getKey().equals("methods")){
										for (Property p1 : link.getStart().getParent().getProperties())
											if(p1.getKey().equals("methods")){
												for(GMethod method : ((GMethods)p.getValue()).getMethods()){
													if(!((GMethods)p1.getValue()).getMethods().contains(method)&& link.getEnd().getParent() instanceof ClassModel &&
															!((GMethods)p1.getValue()).getInheritedMethods().contains(method))
														((GMethods)p1.getValue()).getInheritedMethods().add(method);
													else if(!((GMethods)p1.getValue()).getMethods().contains(method)&& link.getEnd().getParent() instanceof InterfaceModel &&
															!((GMethods)p1.getValue()).getInheritedMethods().contains(method))
														((GMethods)p1.getValue()).getMethods().add(method);
											
												}
												for(GMethod method : ((GMethods)p.getValue()).getInheritedMethods()){
													if(!((GMethods)p1.getValue()).getMethods().contains(method)&& model instanceof ClassModel &&
															!((GMethods)p1.getValue()).getInheritedMethods().contains(method))
														((GMethods)p1.getValue()).getInheritedMethods().add(method);
													else if(!((GMethods)p1.getValue()).getMethods().contains(method)&& model instanceof InterfaceModel &&
															!((GMethods)p1.getValue()).getInheritedMethods().contains(method))
														((GMethods)p1.getValue()).getMethods().add(method);
											
												}
											}
										}
									else {
										for (Property p1 : link.getStart().getParent().getProperties())
											if(p1.getKey().equals("attributes")){
												for(String attribute : ((GAttributes)p.getValue()).getAtributeKeys())
													if(!((GAttributes)p1.getValue()).getAttributes().containsKey(attribute) && !((GAttributes)p1.getValue()).getInheritedAttributes().containsKey(attribute))
														try {													
															((GAttributes)p1.getValue()).getInheritedAttributes().put(attribute, ((GAttributes)p.getValue()).getAtribute(attribute));
														} catch (ElementNePostoji e) { 
														// TODO Auto-generated catch block
														e.printStackTrace();
													}	
												for(String attribute : ((GAttributes)p.getValue()).getInheritedAttributes().keySet())
													if(!((GAttributes)p1.getValue()).getAttributes().containsKey(attribute) && !((GAttributes)p1.getValue()).getInheritedAttributes().containsKey(attribute))													
															((GAttributes)p1.getValue()).getInheritedAttributes().put(attribute, ((GAttributes)p.getValue()).getInheritedAttributes().get(attribute));
											}
									}
								}
						}
					}
					}
			 }
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
						modelEl.setName(txtNameDialog.getText());
						modelEl.setAbstractEl(chbAbstract.isSelected());
						modelEl.setStaticEl(chbStatic.isSelected());
						modelEl.setFinaltEl(chbFinal.isSelected());
						goDepth(modelEl);
						setVisible(false);
			}
		});
		 btnOkDialog.setAlignmentX( 
				Component.CENTER_ALIGNMENT); 
		panSouth.add(Box.createVerticalGlue()); 
		panSouth.add(btnOkDialog); 
		panSouth.add(Box.createVerticalGlue());;
		add(panSouth, BorderLayout.SOUTH);
		btnOkDialog.setText(GMainFrame.getInstance().getResourceBundle().getString("btnOk"));

		this.jtabbed.addTab(GMainFrame.getInstance().getResourceBundle().getString("Atributi"), panTableAttributes);
		this.jtabbed.addTab(GMainFrame.getInstance().getResourceBundle().getString("Metode"), panTableMethods);
		super.add(this.jtabbed, BorderLayout.CENTER);
		
		tableAttributes.getColumnModel().getColumn(0).setMinWidth(100);
		tableAttributes.getColumnModel().getColumn(1).setMinWidth(100);
		tableAttributes.getColumnModel().getColumn(2).setMinWidth(100);
		tableAttributes.getColumnModel().getColumn(3).setMinWidth(100);
		tableAttributes.getColumnModel().getColumn(4).setMinWidth(100);
		tableAttributes.getColumnModel().getColumn(5).setMinWidth(100);
		
		tableMethods.getColumnModel().getColumn(0).setMinWidth(100);
		tableMethods.getColumnModel().getColumn(1).setMinWidth(100);
		tableMethods.getColumnModel().getColumn(2).setMinWidth(100);
		tableMethods.getColumnModel().getColumn(3).setMinWidth(100);
		
		
	}


	@Override
	public void dodavanje() {
		// TODO Auto-generated method stub
		if(this.jtabbed.getSelectedIndex()==0){
		GAttribute novi = new GAttribute();
		PanelDetailAttribute panelDetailDodavanje = new PanelDetailAttribute(StanjeDijaloga.ADD, this, novi);
		AddUpdateDialog addUpdateDialog = new AddUpdateDialog(this, 
				GMainFrame.getInstance().getResourceBundle().getString("DodavanjeAtributa"), StanjeDijaloga.ADD, panelDetailDodavanje);
		addUpdateDialog.setVisible(true);
		
		if (addUpdateDialog.getClosingMode() == AddUpdateDialog.OK) {
			
			novi.setType(panelDetailDodavanje.getTxtType().getText()); 
			novi.setName(panelDetailDodavanje.getTxtName().getText());
			novi.setVisibilityType((String)panelDetailDodavanje.getCmbVisibility().getSelectedItem());
			novi.setPreDef(panelDetailDodavanje.getTxtPredef().getText()); 
			novi.setGetAttribute(panelDetailDodavanje.getChkGetter().isSelected());
			novi.setSetAttribute(panelDetailDodavanje.getChkSetter().isSelected());
			try {
				GAttributes ga = null;
				for (Property p : ((ClassModel)element).getProperties()) {
					if(p.getKey().equals("attributes")){
						((GAttributes)p.getValue()).addAtribute(novi);
					ga = (GAttributes)p.getValue();
					}
				}
				tableModelAttributes.fireTableDataChanged();
				int i = 0;
				for (String key : ga.getAtributeKeys()) {
					{
						if (key.equals(novi.getName()))
						break;
						else i++;
					}
				}
				tableAttributes.changeSelection(i, 0, false, false);
			}catch (ElementPostoji e) {
				JOptionPane.showMessageDialog(ClassModelDialog.this, e.getMessage());
			}
			}
		}	else {
			GMethod novi = new GMethod();
			PanelDetailMethod panelDetailDodavanje = new PanelDetailMethod(StanjeDijaloga.ADD, this, element, novi);
			AddUpdateDialog addUpdateDialog = new AddUpdateDialog(this, 
					GMainFrame.getInstance().getResourceBundle().getString("DodavanjeMetode"), StanjeDijaloga.ADD, panelDetailDodavanje);
			addUpdateDialog.setVisible(true);
			
			if (addUpdateDialog.getClosingMode() == AddUpdateDialog.OK) {
				
				novi.setReturnType(panelDetailDodavanje.getTxtType().getText()); 
				novi.setName(panelDetailDodavanje.getTxtName().getText());
				novi.setVisibilityType((String)panelDetailDodavanje.getCmbVisibility().getSelectedItem());	
				try {
					GMethods ga = null;
					for (Property p : ((ClassModel)element).getProperties()) {
						if(p.getKey().equals("methods")){
							((GMethods)p.getValue()).addMethod(novi);
						ga = (GMethods)p.getValue();
						}
					}
					tableModelMethods.fireTableDataChanged();
					int i = 0;
					for (GMethod key : ga.getMethods()) {
						{
							if (key.equals(novi.getName()) && key.equals(novi.getReturnType()))
							break;
							else i++;
						}
					}
					tableMethods.changeSelection(i, 0, false, false);
				}catch (ElementPostoji e) {
					JOptionPane.showMessageDialog(ClassModelDialog.this, e.getMessage());
				}
				}
		}

	}

	@Override
	public void izmena() {
		// TODO Auto-generated method stub
		if(this.jtabbed.getSelectedIndex()==0){
		if(tableAttributes.getSelectedRow() != -1 )
		{
			int row = tableAttributes.getSelectedRow();
			String name = (String) tableAttributes.getValueAt(row, 2);
			PanelDetailAttribute panelDetailIzmena = null;
			try {
				for (Property p : ((ClassModel)element).getProperties()) {
					if(p.getKey().equals("attributes")){
				panelDetailIzmena = new PanelDetailAttribute(StanjeDijaloga.UPDATE, this, ((GAttributes)p.getValue()).getAtribute(name));
				panelDetailIzmena.getTxtName().setText(((GAttributes)p.getValue()).getAtribute(name).getName());
				panelDetailIzmena.getTxtType().setText(((GAttributes)p.getValue()).getAtribute(name).getType());
				panelDetailIzmena.getCmbVisibility().setSelectedItem(((GAttributes)p.getValue()).getAtribute(name).getVisibility());
				panelDetailIzmena.getTxtPredef().setText(((GAttributes)p.getValue()).getAtribute(name).getPreDef());
				panelDetailIzmena.getChkGetter().setSelected(((GAttributes)p.getValue()).getAtribute(name).isGetAttribute());
				panelDetailIzmena.getChkSetter().setSelected(((GAttributes)p.getValue()).getAtribute(name).isSetAttribute());
					}
				}
			
			} catch (ElementNePostoji e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			AddUpdateDialog addUpdateDialog = new AddUpdateDialog(this, 
				GMainFrame.getInstance().getResourceBundle().getString("IzmenaAtributa"), StanjeDijaloga.UPDATE, panelDetailIzmena);
		addUpdateDialog.setVisible(true);
		
		if (addUpdateDialog.getClosingMode() == addUpdateDialog.OK) {
			try {
			for (Property p : ((ClassModel)element).getProperties()) {
				if(p.getKey().equals("attributes")){
					((GAttributes)p.getValue()).getAtribute(name).setType(panelDetailIzmena.getTxtType().getText());
					((GAttributes)p.getValue()).getAtribute(name).setVisibilityType((String)panelDetailIzmena.getCmbVisibility().getSelectedItem());
					((GAttributes)p.getValue()).getAtribute(name).setPreDef(panelDetailIzmena.getTxtPredef().getText());
					((GAttributes)p.getValue()).getAtribute(name).setName(panelDetailIzmena.getTxtName().getText());
					((GAttributes)p.getValue()).getAtribute(name).setGetAttribute(panelDetailIzmena.getChkGetter().isSelected());
					((GAttributes)p.getValue()).getAtribute(name).setSetAttribute(panelDetailIzmena.getChkSetter().isSelected());
				}
			
			}
			tableModelAttributes.fireTableDataChanged();
			tableAttributes.changeSelection(row, 0, false, false);
			} catch (ElementNePostoji e) {
				JOptionPane.showMessageDialog(ClassModelDialog.this, e.getMessage());
			}
		
			
		}

		}
		} else {
			if(tableMethods.getSelectedRow() != -1 )
			{
				PanelDetailMethod panelDetailIzmena = null;
				int row = tableMethods.getSelectedRow();
				String name = (String) tableMethods.getValueAt(row, 2);
				try {
					for (Property p : ((ClassModel)element).getProperties()) {
						if(p.getKey().equals("methods")){
					panelDetailIzmena = new PanelDetailMethod(StanjeDijaloga.UPDATE, this, element, ((GMethods)p.getValue()).getMethod(name));
					panelDetailIzmena.getTxtName().setText(((GMethods)p.getValue()).getMethod(name).getName());
					panelDetailIzmena.getTxtType().setText(((GMethods)p.getValue()).getMethod(name).getReturnType());
					panelDetailIzmena.getCmbVisibility().setSelectedItem(((GMethods)p.getValue()).getMethod(name).getVisibility());
					}
					}
				
				} catch (ElementNePostoji e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				AddUpdateDialog addUpdateDialog = new AddUpdateDialog(this, 
					GMainFrame.getInstance().getResourceBundle().getString("IzmenaMetode"), StanjeDijaloga.UPDATE, panelDetailIzmena);
			addUpdateDialog.setVisible(true);
			
			if (addUpdateDialog.getClosingMode() == addUpdateDialog.OK) {
				for (Property p : ((ClassModel)element).getProperties()) {
					if(p.getKey().equals("methods")){
						((GMethods)p.getValue()).getMethodbyName(name).setVisibilityType((String)panelDetailIzmena.getCmbVisibility().getSelectedItem());
						((GMethods)p.getValue()).getMethodbyName(name).setReturnType(panelDetailIzmena.getTxtType().getText());
						((GMethods)p.getValue()).getMethodbyName(name).setName(panelDetailIzmena.getTxtName().getText());
					}
				
				}
				tableModelMethods.fireTableDataChanged();
				tableMethods.changeSelection(row, 0, false, false);
			
				
			}
			}
		}
	}

	@Override
	public void brisanje() {
		// TODO Auto-generated method stub
		if(this.jtabbed.getSelectedIndex()==0){
		if(tableAttributes.getSelectedRow() != -1 )
		{
			
			int row = tableAttributes.getSelectedRow();
			String name = (String) tableAttributes.getValueAt(row, 2);
			GAttribute attribute = null;
			try {
				for (Property p : ((ClassModel)element).getProperties()) {
					if(p.getKey().equals("attributes")){						
				attribute = ((GAttributes)p.getValue()).getAtribute(name);
				((GAttributes)p.getValue()).removeAtribute(attribute);
				tableModelAttributes.fireTableDataChanged();
					}
				}
			} catch (ElementNePostoji e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
							
						
		}
			
	} else {
		if(tableMethods.getSelectedRow() != -1 )
		{
			
			int row = tableMethods.getSelectedRow();
			String name = (String) tableMethods.getValueAt(row, 2);
			GMethod method = null;
			try {
				for (Property p : ((ClassModel)element).getProperties()) {
					if(p.getKey().equals("methods")){						
						method = ((GMethods)p.getValue()).getMethod(name);
						((GMethods)p.getValue()).removeMethod(method);
						tableModelMethods.fireTableDataChanged();
					}
				}
			} catch (ElementNePostoji e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
	}

	}
	}

}
